home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / jpl_c.zip / UNFORMAT.C < prev    next >
Text File  |  1988-08-06  |  6KB  |  266 lines

  1. /* 1.1  01-08-86                         (unformat.c)
  2.  ************************************************************************
  3.  *            Robert C. Tausworthe                *
  4.  *            Jet Propulsion Laboratory            *
  5.  *            Pasadena, CA 91009        1986        *
  6.  ************************************************************************/
  7.  
  8. #include "defs.h"
  9. #include "stdtyp.h"
  10. #include "stdio.h"
  11.  
  12. #define    NEXT        TRUE    /* Forward direction for getting chars.    */
  13. #define BACK        FALSE    /* Reverse direction for getting chars.    */
  14. #define LONGTYP        TRUE    /* Value to signal long or double.    */
  15. #define NORMTYP        FALSE    /* Value to denote normal width number.    */
  16. #define SHORTTYP    -TRUE    /* Value to denote short rather than int*/
  17.  
  18. /*----------------------------------------------------------------------*/
  19.  
  20. LOCAL int     width;
  21. LOCAL int     (*xgetc)();
  22. STRING        index();
  23.  
  24. /************************************************************************/
  25.  
  26. unformat(getch, fmt, arglist)    /* Perform scanf() on getch input medium,
  27.                    using format fmt and argument list
  28.                    pointed to by arglist. Returns number of
  29.                    matched and assigned input items, or
  30.                    EOF if input finished before fmt.    */
  31. /*----------------------------------------------------------------------*/
  32. int (*getch)();            /* Note:  getch(NEXT) performs a    */
  33. FAST STRING fmt;        /* getc(medium), and getch(BACK) does    */
  34. int **arglist;            /* an ungetc(c, medium).        */
  35. {
  36.     FAST int c;
  37.     double nxtfloat(), d;
  38.     long nxtnumber(), val;
  39.     int count, base;
  40.     STRING s;
  41.     BOOL suppress, numtyp;
  42.     char wkbuf[MAXLINE];
  43.  
  44.     count = 0;
  45.     xgetc = getch;
  46. /*\p*/
  47.     while (c = *fmt++)
  48.     {    if (c IS '%')
  49.         {    numtyp = NORMTYP;
  50.             suppress = FALSE;
  51.             width = MAXLINE;
  52.             if (*fmt IS '*')
  53.             {    ++fmt;
  54.                 suppress = TRUE;
  55.             }
  56.             if (isdigit(*fmt))
  57.             {    width = 0;
  58.                 do
  59.                 {    width *= 10;
  60.                     width += (*fmt - '0');
  61.                 } while (isdigit(*++fmt));
  62.             }
  63.             if (*fmt IS 'l')
  64.             {    numtyp = LONGTYP;
  65.                 ++fmt;
  66.             }
  67.             if (*fmt IS 'h')
  68.             {    numtyp = SHORTTYP;
  69.                 ++fmt;
  70.             }
  71.             if (index("DOXEF", c = *fmt++))
  72.                 numtyp = LONGTYP;
  73.             switch (c = tolower(c))
  74.             {   case ' ':
  75.                 fmt--;
  76.                 if (numtyp IS SHORTTYP)
  77.                     c = 'd';
  78.                 else
  79.                     break;
  80.                 case 'd':
  81.                 case 'o':
  82.                 case 'x':
  83.                 base = (c IS 'd'? 10 : (c IS 'o' ? 8 : 16));
  84.                 if (eatblanks())
  85.                     return (count ? count : EOF);
  86.  
  87.                 val = nxtnumber(base);
  88.                 if (NOT suppress)
  89.                 {    if (numtyp IS LONGTYP)
  90.                         *(long *)(*arglist++) = val;
  91.                     else if (numtyp IS SHORTTYP)
  92.                         *(short *)(*arglist++) = val;
  93.                     else
  94.                         **arglist++ = val;
  95.                     ++count;
  96.                 }
  97.                 break;
  98. /*\p*/
  99.                 case 'e':
  100.                 case 'f':
  101.                 if (eatblanks())
  102.                     return (count ? count : EOF);
  103.  
  104.                 d = nxtfloat(wkbuf);
  105.                 if (NOT suppress)
  106.                 {    if (numtyp IS LONGTYP)
  107.                         *(double *)(*arglist++) = d;
  108.                     else
  109.                         *(float *)(*arglist++) = d;
  110.                     ++count;
  111.                 }
  112.                 break;
  113.                 case '[':
  114.                 case 's':
  115.                 if (c IS '[')
  116.                 {    if (*fmt IS '^' OR *fmt IS '~')
  117.                     {    numtyp = NORMTYP;
  118.                         ++fmt;
  119.                     }
  120.                     else
  121.                         numtyp = LONGTYP;
  122.                     for (s = wkbuf;(c = *fmt++) ISNT ']';)
  123.                         *s++ = c;
  124.                     *s = NULL;
  125.                 }
  126.                 else
  127.                 {    numtyp = NORMTYP;
  128.                     strcpy(wkbuf, " \t\n");
  129.                 }
  130.                 if (eatblanks())
  131.                     return (count ? count : EOF);
  132.  
  133.                 if (NOT suppress)
  134.                     s = (STRING) *arglist++;
  135.                 while (width--)
  136.                 {    if ((c = (*xgetc)(NEXT)) IS EOF)
  137.                         break;
  138.                     if (numtyp IS NORMTYP ?
  139.                         (index(wkbuf, c) ISNT NULL) :
  140.                         (index(wkbuf, c)  IS  NULL))
  141.                     {    (*xgetc)(BACK);    
  142.                         break;
  143.                     }
  144.                     if (NOT suppress)
  145.                         *s++ = c;
  146.                 }
  147.                 if (NOT suppress)
  148.                 {    *s = NULL;
  149.                     ++count;
  150.                 }
  151.                 break;
  152. /*\p*/
  153.                 case 'c':
  154.                 if ((c = (*xgetc)(NEXT)) IS EOF)
  155.                     return (count ? count : EOF);
  156.  
  157.                 if (NOT suppress)
  158.                 {    *(STRING)(*arglist++) = c;
  159.                     ++count;
  160.                 }
  161.                 break;
  162.                 case '%':
  163.                 goto match;
  164.             }
  165.         }
  166.         else if (isspace(c))
  167.         {    if (eatblanks())
  168.                 return (count ? count : EOF);
  169.         }
  170.         else
  171.         {
  172. match:            if (eatblanks())
  173.                 return (count ? count : EOF);
  174.  
  175.             if ((*xgetc)(NEXT) ISNT c)
  176.                 return count;
  177.         }
  178.     }
  179.     return count;
  180. }
  181.  
  182. /************************************************************************/
  183.     LOCAL BOOL
  184. eatblanks()        /* Get characters from input medium until no longer
  185.                whitespace.  Return FALSE normally, or TRUE at 
  186.                end of line.                    */
  187. /*----------------------------------------------------------------------*/
  188. {
  189. char c;
  190.     while (isspace(c = (*xgetc)(NEXT)))
  191.         ;
  192.     if ((*xgetc)(BACK) IS EOF)
  193.         return TRUE;
  194.     else
  195.         return FALSE;
  196. }
  197. /*\p*********************************************************************/
  198.     LOCAL double
  199. nxtfloat(buffer)    /* Get the next ascii e-form or f-form from the
  200.                input medium, and return its value. Store
  201.                the ascii form in buffer.            */
  202. /*----------------------------------------------------------------------*/
  203. STRING buffer;
  204. {
  205.     FAST int c;
  206.     FAST STRING s;
  207.     TBOOL decmlpt, sign, exp;
  208.     double atof();
  209.  
  210.     s = buffer;
  211.     sign = exp = decmlpt = FALSE;
  212.     while (width--)
  213.     {    c = (*xgetc)(NEXT);
  214.         if (NOT sign AND (c IS '-' OR c IS '+'))
  215.             sign = TRUE;
  216.         else if (NOT decmlpt AND c IS '.')
  217.             sign = decmlpt = TRUE;
  218.         else if (NOT exp AND (c IS 'e' OR c IS 'E'))
  219.         {    sign = FALSE;
  220.             exp = decmlpt = TRUE;
  221.         }
  222.         else if (NOT isdigit(c))
  223.         {    (*xgetc)(BACK);
  224.             break;
  225.         }
  226.         *s++ = c;
  227.     }
  228.     *s = 0;
  229.     return atof(buffer);
  230. }
  231. /*\p*********************************************************************/
  232.     LOCAL long
  233. nxtnumber(base)        /* Get the ascii string of a number with given 
  234.                base from input medium, return its value.    */
  235. /*----------------------------------------------------------------------*/
  236. {
  237.     int c;
  238.     long value;
  239.     BOOL minus;
  240.     LOCAL char digits[] = "0123456789abcdef";
  241.  
  242.     if (width <= 0)
  243.         return 0L;
  244.  
  245.     value = 0;
  246.     minus = FALSE;
  247.     if ((c = (*xgetc)(NEXT)) IS '-')
  248.     {    minus = TRUE;
  249.         --width;
  250.     }
  251.     else if (c IS '+')
  252.         --width;
  253.     else
  254.         (*xgetc)(BACK);
  255.     while (width--)
  256.     {    c = index(digits, tolower((*xgetc)(NEXT))) - digits;
  257.         if (c < 0 OR c >= base)
  258.         {    (*xgetc)(BACK);
  259.             break;
  260.         }
  261.         value *= base;
  262.         value += c;
  263.     }
  264.     return (minus ? -value : value);
  265. }
  266.